package com.android.common.base;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.net.Network;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Toast;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.databinding.DataBindingUtil;
import androidx.databinding.ViewDataBinding;
import androidx.fragment.app.Fragment;
import com.android.common.R;
import com.android.common.constant.Constant;
import com.android.common.mvp.model.CodeMsgBean;
import com.android.common.mvp.view.ExceptionView;
import com.android.common.mvp.view.ToolBarBinding;
import com.android.common.network.CustomNetworkCallback;
import com.android.common.network.NetWorkConnectInfo;
import com.android.common.network.NetworkConnectListener;
import com.android.common.utils.AppUtils;
import com.android.common.utils.FragmentStack;
import com.android.common.utils.permission.FragmentPermissionDispatcher;
import com.android.common.utils.permission.PermissionCallback;
import com.android.common.widget.AllDialog;
import com.android.common.widget.DialogFactory;
import java.util.Objects;
import org.greenrobot.eventbus.EventBus;

/**
 * Fragment基类
 * @param <VDB> mvvm 下的ViewDataBinding
 */
public abstract class BaseFragment<VDB extends ViewDataBinding> extends Fragment
    implements BaseView, PermissionCallback, ToolBarBinding.BackClickListener, NetworkConnectListener{
    protected VDB mViewDataBinding;
    protected Activity mActivity;
    protected LinearLayout mRootView;
    protected ConstraintLayout mToolBar;
    protected ToolBarBinding mToolBarBinding;
    protected FrameLayout mFlRootContent;
    protected LayoutInflater mLayoutInflater;
    protected Bundle mBundle;
    protected ExceptionView mErrorView;
    protected AllDialog mLoadingDialog;
    private FragmentPermissionDispatcher dispatcher;

    public BaseFragment() {
    }

    @Override
    public void onAttach(@NonNull Context context) {
        super.onAttach(context);
        OnBackPressedCallback callback = new OnBackPressedCallback(true) {
            @Override
            public void handleOnBackPressed() {
                onBackPressed();
            }
        };
        requireActivity().getOnBackPressedDispatcher().addCallback(
                this, callback);
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        FragmentStack.getInstance().add(this);
        this.mActivity = this.getActivity();
        this.mBundle = this.getArguments();
        if (this.mBundle == null) {
            this.mBundle = new Bundle();
        }
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        mLayoutInflater = inflater;
        mRootView = (LinearLayout) mLayoutInflater.inflate(R.layout.fragment_base, container, false);
        mToolBar = mRootView.findViewById(R.id.cl_toolbar);
        mFlRootContent = mRootView.findViewById(R.id.fl_root_content);
        mViewDataBinding = DataBindingUtil.inflate(mLayoutInflater, onSetRootViewId(), mFlRootContent, true);
        mToolBarBinding = new ToolBarBinding(mToolBar);
        if (onNeedSpecialErrorView()) {
            addSpecialErrorView();
        }
        mErrorView = mRootView.findViewById(R.id.errorView);

        if (mErrorView != null) {
            initErrorView();
        }

        if (!onNeedToolBar()) {
            mToolBar.setVisibility(View.GONE);
        }

        mToolBarBinding.showBack(onNeedBack());
        mToolBarBinding.setTitleText(onSetTitleText());
        mToolBarBinding.setBackClickListener(this);

        if (onSetToolbarRightViewId() != Constant.INVALID){
            View toolbarRightViews = mLayoutInflater.inflate(onSetToolbarRightViewId(),null);
            mToolBarBinding.setToolbarRightViews(toolbarRightViews);
            onInitToolbarRightViews(toolbarRightViews);
        }

        return this.mRootView;
    }

    protected boolean onNeedEventBus() {
        return false;
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        if (onNeedEventBus()) {
            if (!EventBus.getDefault().isRegistered(this)) {
                EventBus.getDefault().register(this);
            }
        }
        onFindView();
        onInitView();
        onInitEvent();
        this.onLoadData();
        if (onNeedRequestPermission()){
            initPermission();
        }
        if (onNeedNetworkListener()){
            registerNetworkListener();
        }
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this);
        }
        if (onNeedNetworkListener()){
            unRegisterNetworkListener();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        hideProgress();
        mLoadingDialog = null;
        FragmentStack.getInstance().remove(this);
        if (null != dispatcher){
            dispatcher.clear(this);
        }
    }

    @SuppressLint("MissingPermission")
    private void registerNetworkListener(){
        CustomNetworkCallback networkCallback = CustomNetworkCallback.getInstance();
        networkCallback.setListener(this);
        NetWorkConnectInfo.getConnectivityManager().registerDefaultNetworkCallback(networkCallback);
    }

    @SuppressLint("MissingPermission")
    private void unRegisterNetworkListener(){
        CustomNetworkCallback networkCallback = CustomNetworkCallback.getInstance();
        NetWorkConnectInfo.getConnectivityManager().unregisterNetworkCallback(networkCallback);
    }

    private void addSpecialErrorView() {
        mFlRootContent.addView(mLayoutInflater.inflate(R.layout.layout_special_error_view, mRootView, false));
    }

    protected void setErrorViewTopMargin(int topMargin){
        if (null == mErrorView) return;
        FrameLayout.LayoutParams lp =  (FrameLayout.LayoutParams)mErrorView.getLayoutParams();
        lp.topMargin = topMargin;
        mErrorView.setLayoutParams(lp);
    }

    protected boolean onNeedSpecialErrorView() {
        return false;
    }

    public void initErrorView() {
        if (mErrorView != null) {
            mErrorView.setOnReloadListener(v -> onErrorClick());
        }
    }

    public void onErrorClick() {
        if (mErrorView != null) {
            mErrorView.hide();
        }
        onLoadData();
    }

    protected abstract int onSetRootViewId();

    protected void onFindView() {
    }

    protected void onInitView() {
    }

    protected void onInitEvent() {
    }

    protected void onLoadData() {
    }

    protected void onBackPressed() {
        requireActivity().finish();
    }

    //toolbar start
    protected boolean onNeedToolBar() {
        return true;
    }

    protected boolean onNeedBack() {
        return true;
    }

    protected boolean onNeedRequestPermission(){
        return true;
    }

    protected String onSetTitleText() {
        return "";
    }

    protected boolean onNeedNetworkListener() {
        return false;
    }

    @Override
    public void onBackClickListener() {
        requireActivity().finish();
    }

    protected int onSetToolbarRightViewId(){
        return Constant.INVALID;
    }

    //初始化Toolbar右边的view
    protected void onInitToolbarRightViews(View views){

    }
    //toolbar end

    private void initPermission() {
        dispatcher = FragmentPermissionDispatcher.getInstance();
        dispatcher.setPermissionCallback(this, this);
        dispatcher.checkedWithStorage(this);
    }

    public boolean isAlive() {
        return AppUtils.isAlive(this);
    }

    /**
     * 显示加载框
     */
    public void showProgress() {
        if (isAlive() && !isDetached()) {
            if (mLoadingDialog == null) {
                mLoadingDialog = DialogFactory.createLoading(mActivity);
            }
            mLoadingDialog.show();
        }
    }

    public boolean isProgressShown() {
        return mLoadingDialog != null && mLoadingDialog.isShowing();
    }

    public void hideProgress() {
        if (isProgressShown()) {
            mLoadingDialog.dismiss();
        }
    }

    @Override
    public void onFailed(CodeMsgBean responseBean, String methodName) {
        hideProgress();
        Toast.makeText(getContext(), responseBean.getMessage() + "[code = " + responseBean.getCode() + "]", Toast.LENGTH_LONG).show();
    }

    @Override
    public <D> void onSucceed(D d,String methodName) {
        hideProgress();
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        dispatcher.onRequestPermissionResult(this, requestCode, grantResults);
    }

    /**
     * 监听网络：可用状态
     */
    @Override
    public void onNetworkAvailable(@NonNull Network network) {
        if (isAlive()) {
            Toast.makeText(getContext(), com.android.resource.R.string.network_available,Toast.LENGTH_SHORT).show();
        }
    }
    /**
     * 监听网络：不可用状态
     */
    @Override
    public void onNetworkUnavailable() {
        if (isAlive()) {
            Toast.makeText(getContext(),com.android.resource.R.string.network_un_available,Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 监听网络：已断开状态
     */
    @Override
    public void onNetworkLost(@NonNull Network network) {
        if (isAlive()) {
            Toast.makeText(getContext(), com.android.resource.R.string.network_lost,Toast.LENGTH_SHORT).show();
        }
    }

    /**
     * 权限申请回调
     *
     * @param request  申请code
     * @param state    状态
     */
    @Override
    public void onPermission(int request, int state) {
        switch (request) {
            case Constant.PERMISSION_STORAGE_REQUEST_CODE:
                switch (state) {
                    case PermissionCallback.SUCCESS:
                    case PermissionCallback.DENIED:
                    case PermissionCallback.NEVER_ASK_AGAIN:
                    case PermissionCallback.EXPLAIN:
                        dispatcher.checkedWithCamera(this);
                        break;
                }
                break;
            case Constant.PERMISSION_CAMERA_REQUEST_CODE:
                switch (state) {
                    case PermissionCallback.SUCCESS:
                    case PermissionCallback.DENIED:
                    case PermissionCallback.NEVER_ASK_AGAIN:
                    case PermissionCallback.EXPLAIN:
                        dispatcher.checkedWithLocation(this);
                        break;
                }
                break;
            case Constant.PERMISSION_LOCATION_REQUEST_CODE:
                switch (state) {
                    case PermissionCallback.SUCCESS:
                    case PermissionCallback.DENIED:
                    case PermissionCallback.NEVER_ASK_AGAIN:
                    case PermissionCallback.EXPLAIN:
                        break;
                }
                break;
        }
    }
}
